#pragma once
#include <string>
#include <pthread.h>
#include <queue>
#include <vector>
#include "Thread.hpp"
#include <functional>
#include <iostream>
#include "LockGuard.hpp"
#include "Log.hpp"
const int defaultnum = 5;

class ThreadData
{
public:
    ThreadData(std::string threadname)
    :_threadname(threadname)
    {}
public:
    std::string _threadname;
};

template<class T>
class ThreadPool
{
public:
    ThreadPool(int threadnum = defaultnum)
    :_threadnum(threadnum)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        std::cout << "ThreadPool构造" << std::endl; //debug 
        for(int i = 1; i <= _threadnum; i++)
        {
            std::string threadname = "thread-";
            threadname += std::to_string(i);
            // std::cout << "Thread name: " << threadname << std::endl;  //threadname √
            lg.LogMessage(Info, "%s is created\n", threadname.c_str());
            // Thread(threadname, bind(&ThreadRun, this, std::placeholders::_1), ThreadData(threadname)); //TODO
            _threads.emplace_back(threadname, bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), ThreadData(threadname)); //TODO
        
        }
    }
    static ThreadPool<T> *GetInstance()
    {
        if (instance == nullptr)
        {
            LockGuard lockguard(&sig_lock);
            if (instance == nullptr)
            {
                // lg.LogMessage(Info, "创建单例成功...\n");
                instance = new ThreadPool<T>();
            }
        }

        return instance;
    }
    void Start()
    {
        for(int i = 0; i < _threadnum; i++)
            _threads[i].Start();
    }
    void ThreadRun(ThreadData& td)
    {
        while(true)
        {
            T t;
            {
                LockGuard lock(&_mutex);
                while(_q.empty())
                {
                    // std::cout << _q.size(); //那怪有0
                    pthread_cond_wait(&_cond, &_mutex);
                }
                t = _q.front();
                _q.pop();
            }
            t(); //执行task函数对象
            // std::cout << td._threadname << " :"<< t.PrintResult() << std::endl;
        }
    }
    void Push(const T& in)
    {
        LockGuard lock(&_mutex);
        _q.push(in);
        pthread_cond_signal(&_cond);
    }
    void Join()
    {
        for(int i = 0; i < _threadnum; i++)
            _threads[i].Join();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
private:
    std::queue<T> _q;
    std::vector<Thread<ThreadData>> _threads;
    int _threadnum;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;


    static ThreadPool<T> *instance;
    static pthread_mutex_t sig_lock;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::instance = nullptr;
template<class T>
pthread_mutex_t ThreadPool<T>::sig_lock = PTHREAD_MUTEX_INITIALIZER;